package net.danielthompson.danray.structures;

import net.danielthompson.danray.lights.Radiatable;
import net.danielthompson.danray.shapes.*;
import net.danielthompson.danray.states.IntersectionState;
import net.danielthompson.danray.cameras.Camera;


import java.util.ArrayList;
import java.util.List;

/**
 * DanRay
 * User: dthompson
 * Date: 6/28/13
 * Time: 5:24 PM
 */
public class Scene {
   /*
   The drawables in this scene.
    */
   private List<Drawable> _drawables;

   public List<Radiatable> getRadiatables() {
      return _radiatables;
   }

   public List<Drawable> getDrawables() {
      return _drawables;
   }

   private List<Radiatable> _radiatables;

   public Camera Camera;

   private BoundingBox _boundingBox;

   public Scene(Camera camera) {
      Camera = camera;
      _drawables = new ArrayList<Drawable>();
      _radiatables = new ArrayList<Radiatable>();
   }

   public void AddDrawableObject(Drawable drawable) {
      _drawables.add(drawable);
   }

   public void AddRadiatableObject(Radiatable radiatable) {
      _radiatables.add(radiatable);
   }

   public static BoundingBox BuildBoundingVolumeHeirarchy(List<Boundable> boundables) {
      // base case
      if (boundables.size() == 1)
         return boundables.get(1).GetBoundingBox();

      // recursive case
      double[][] volume = new double[boundables.size()][boundables.size()];

      for (int i = 0; i < boundables.size() - 1; i++) {
         for (int j = i + 1; j < boundables.size(); j++) {
            if (boundables.get(i) == boundables.get(j))
               continue;
            BoundingBox potential = BoundingBox.GetBoundingBox(boundables.get(i).GetBoundingBox(), boundables.get(j).GetBoundingBox());
            volume[i][j] = potential.GetVolume();
         }
      }

      return null; //TODO
   }

   public IntersectionState GetClosestDrawableToRay(Vector ray) {
      IntersectionState closestStateToRay = null;

      for (Drawable drawable : _drawables) {
         IntersectionState state = drawable.GetHitInfo(ray);

         if (state.Hits) {
            if (closestStateToRay == null) {
               closestStateToRay = state;
            }
            if (state.T < closestStateToRay.T) {
               closestStateToRay = state;
            }
         }
      }

      return closestStateToRay;
   }
}